From: Greg Kroah-Hartman Date: Thu, 3 Oct 2019 15:18:23 +0000 (+0200) Subject: drop fuse patch that didn't need to be backported as far. X-Git-Tag: v4.4.195~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=adbaa183e4970af0c3215f53dd5a9424a6d410ea;p=thirdparty%2Fkernel%2Fstable-queue.git drop fuse patch that didn't need to be backported as far. --- diff --git a/queue-4.14/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch b/queue-4.14/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch deleted file mode 100644 index c81eb80979d..00000000000 --- a/queue-4.14/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch +++ /dev/null @@ -1,401 +0,0 @@ -From 893cbb6cdc091ab6da8f0590ca625cc58e5650d2 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Sun, 8 Sep 2019 20:15:18 -0700 -Subject: fuse: fix deadlock with aio poll and fuse_iqueue::waitq.lock - -From: Eric Biggers - -[ Upstream commit 76e43c8ccaa35c30d5df853013561145a0f750a5 ] - -When IOCB_CMD_POLL is used on the FUSE device, aio_poll() disables IRQs -and takes kioctx::ctx_lock, then fuse_iqueue::waitq.lock. - -This may have to wait for fuse_iqueue::waitq.lock to be released by one -of many places that take it with IRQs enabled. Since the IRQ handler -may take kioctx::ctx_lock, lockdep reports that a deadlock is possible. - -Fix it by protecting the state of struct fuse_iqueue with a separate -spinlock, and only accessing fuse_iqueue::waitq using the versions of -the waitqueue functions which do IRQ-safe locking internally. - -Reproducer: - - #include - #include - #include - #include - #include - #include - #include - - int main() - { - char opts[128]; - int fd = open("/dev/fuse", O_RDWR); - aio_context_t ctx = 0; - struct iocb cb = { .aio_lio_opcode = IOCB_CMD_POLL, .aio_fildes = fd }; - struct iocb *cbp = &cb; - - sprintf(opts, "fd=%d,rootmode=040000,user_id=0,group_id=0", fd); - mkdir("mnt", 0700); - mount("foo", "mnt", "fuse", 0, opts); - syscall(__NR_io_setup, 1, &ctx); - syscall(__NR_io_submit, ctx, 1, &cbp); - } - -Beginning of lockdep output: - - ===================================================== - WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected - 5.3.0-rc5 #9 Not tainted - ----------------------------------------------------- - syz_fuse/135 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: - 000000003590ceda (&fiq->waitq){+.+.}, at: spin_lock include/linux/spinlock.h:338 [inline] - 000000003590ceda (&fiq->waitq){+.+.}, at: aio_poll fs/aio.c:1751 [inline] - 000000003590ceda (&fiq->waitq){+.+.}, at: __io_submit_one.constprop.0+0x203/0x5b0 fs/aio.c:1825 - - and this task is already holding: - 0000000075037284 (&(&ctx->ctx_lock)->rlock){..-.}, at: spin_lock_irq include/linux/spinlock.h:363 [inline] - 0000000075037284 (&(&ctx->ctx_lock)->rlock){..-.}, at: aio_poll fs/aio.c:1749 [inline] - 0000000075037284 (&(&ctx->ctx_lock)->rlock){..-.}, at: __io_submit_one.constprop.0+0x1f4/0x5b0 fs/aio.c:1825 - which would create a new lock dependency: - (&(&ctx->ctx_lock)->rlock){..-.} -> (&fiq->waitq){+.+.} - - but this new dependency connects a SOFTIRQ-irq-safe lock: - (&(&ctx->ctx_lock)->rlock){..-.} - - [...] - -Reported-by: syzbot+af05535bb79520f95431@syzkaller.appspotmail.com -Reported-by: syzbot+d86c4426a01f60feddc7@syzkaller.appspotmail.com -Fixes: bfe4037e722e ("aio: implement IOCB_CMD_POLL") -Cc: # v4.19+ -Cc: Christoph Hellwig -Signed-off-by: Eric Biggers -Signed-off-by: Miklos Szeredi -Signed-off-by: Sasha Levin ---- - fs/fuse/dev.c | 89 +++++++++++++++++++++++++----------------------- - fs/fuse/fuse_i.h | 3 ++ - fs/fuse/inode.c | 1 + - 3 files changed, 50 insertions(+), 43 deletions(-) - -diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c -index f580695b7bb9a..368acbbff4bb2 100644 ---- a/fs/fuse/dev.c -+++ b/fs/fuse/dev.c -@@ -324,7 +324,7 @@ static void queue_request(struct fuse_iqueue *fiq, struct fuse_req *req) - req->in.h.len = sizeof(struct fuse_in_header) + - len_args(req->in.numargs, (struct fuse_arg *) req->in.args); - list_add_tail(&req->list, &fiq->pending); -- wake_up_locked(&fiq->waitq); -+ wake_up(&fiq->waitq); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - } - -@@ -336,16 +336,16 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, - forget->forget_one.nodeid = nodeid; - forget->forget_one.nlookup = nlookup; - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (fiq->connected) { - fiq->forget_list_tail->next = forget; - fiq->forget_list_tail = forget; -- wake_up_locked(&fiq->waitq); -+ wake_up(&fiq->waitq); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - } else { - kfree(forget); - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - } - - static void flush_bg_queue(struct fuse_conn *fc) -@@ -358,10 +358,10 @@ static void flush_bg_queue(struct fuse_conn *fc) - req = list_entry(fc->bg_queue.next, struct fuse_req, list); - list_del(&req->list); - fc->active_background++; -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - req->in.h.unique = fuse_get_unique(fiq); - queue_request(fiq, req); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - } - } - -@@ -380,9 +380,9 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) - if (test_and_set_bit(FR_FINISHED, &req->flags)) - goto put_request; - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - list_del_init(&req->intr_entry); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - WARN_ON(test_bit(FR_PENDING, &req->flags)); - WARN_ON(test_bit(FR_SENT, &req->flags)); - if (test_bit(FR_BACKGROUND, &req->flags)) { -@@ -420,16 +420,16 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) - - static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) - { -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (test_bit(FR_FINISHED, &req->flags)) { -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - return; - } - if (list_empty(&req->intr_entry)) { - list_add_tail(&req->intr_entry, &fiq->interrupts); - wake_up_locked(&fiq->waitq); - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - } - -@@ -459,16 +459,16 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) - if (!err) - return; - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - /* Request is not yet in userspace, bail out */ - if (test_bit(FR_PENDING, &req->flags)) { - list_del(&req->list); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - __fuse_put_request(req); - req->out.h.error = -EINTR; - return; - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - } - - /* -@@ -483,9 +483,9 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) - struct fuse_iqueue *fiq = &fc->iq; - - BUG_ON(test_bit(FR_BACKGROUND, &req->flags)); -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (!fiq->connected) { -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - req->out.h.error = -ENOTCONN; - } else { - req->in.h.unique = fuse_get_unique(fiq); -@@ -493,7 +493,7 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) - /* acquire extra reference, since request is still needed - after request_end() */ - __fuse_get_request(req); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - request_wait_answer(fc, req); - /* Pairs with smp_wmb() in request_end() */ -@@ -626,12 +626,12 @@ static int fuse_request_send_notify_reply(struct fuse_conn *fc, - - __clear_bit(FR_ISREPLY, &req->flags); - req->in.h.unique = unique; -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (fiq->connected) { - queue_request(fiq, req); - err = 0; - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - return err; - } -@@ -1075,12 +1075,12 @@ static int request_pending(struct fuse_iqueue *fiq) - * Unlike other requests this is assembled on demand, without a need - * to allocate a separate fuse_req structure. - * -- * Called with fiq->waitq.lock held, releases it -+ * Called with fiq->lock held, releases it - */ - static int fuse_read_interrupt(struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, - size_t nbytes, struct fuse_req *req) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - struct fuse_in_header ih; - struct fuse_interrupt_in arg; -@@ -1096,7 +1096,7 @@ __releases(fiq->waitq.lock) - ih.unique = req->intr_unique; - arg.unique = req->in.h.unique; - -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - if (nbytes < reqsize) - return -EINVAL; - -@@ -1133,7 +1133,7 @@ static struct fuse_forget_link *dequeue_forget(struct fuse_iqueue *fiq, - static int fuse_read_single_forget(struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, - size_t nbytes) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - int err; - struct fuse_forget_link *forget = dequeue_forget(fiq, 1, NULL); -@@ -1147,7 +1147,7 @@ __releases(fiq->waitq.lock) - .len = sizeof(ih) + sizeof(arg), - }; - -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - kfree(forget); - if (nbytes < ih.len) - return -EINVAL; -@@ -1165,7 +1165,7 @@ __releases(fiq->waitq.lock) - - static int fuse_read_batch_forget(struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, size_t nbytes) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - int err; - unsigned max_forgets; -@@ -1179,13 +1179,13 @@ __releases(fiq->waitq.lock) - }; - - if (nbytes < ih.len) { -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - return -EINVAL; - } - - max_forgets = (nbytes - ih.len) / sizeof(struct fuse_forget_one); - head = dequeue_forget(fiq, max_forgets, &count); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - arg.count = count; - ih.len += count * sizeof(struct fuse_forget_one); -@@ -1215,7 +1215,7 @@ __releases(fiq->waitq.lock) - static int fuse_read_forget(struct fuse_conn *fc, struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, - size_t nbytes) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - if (fc->minor < 16 || fiq->forget_list_head.next->next == NULL) - return fuse_read_single_forget(fiq, cs, nbytes); -@@ -1244,16 +1244,19 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, - unsigned reqsize; - - restart: -- spin_lock(&fiq->waitq.lock); -- err = -EAGAIN; -- if ((file->f_flags & O_NONBLOCK) && fiq->connected && -- !request_pending(fiq)) -- goto err_unlock; -+ for (;;) { -+ spin_lock(&fiq->lock); -+ if (!fiq->connected || request_pending(fiq)) -+ break; -+ spin_unlock(&fiq->lock); - -- err = wait_event_interruptible_exclusive_locked(fiq->waitq, -+ if (file->f_flags & O_NONBLOCK) -+ return -EAGAIN; -+ err = wait_event_interruptible_exclusive(fiq->waitq, - !fiq->connected || request_pending(fiq)); -- if (err) -- goto err_unlock; -+ if (err) -+ return err; -+ } - - err = -ENODEV; - if (!fiq->connected) -@@ -1276,7 +1279,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, - req = list_entry(fiq->pending.next, struct fuse_req, list); - clear_bit(FR_PENDING, &req->flags); - list_del_init(&req->list); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - in = &req->in; - reqsize = in->h.len; -@@ -1339,7 +1342,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, - return err; - - err_unlock: -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - return err; - } - -@@ -2050,12 +2053,12 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait) - fiq = &fud->fc->iq; - poll_wait(file, &fiq->waitq, wait); - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (!fiq->connected) - mask = POLLERR; - else if (request_pending(fiq)) - mask |= POLLIN | POLLRDNORM; -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - return mask; - } -@@ -2146,15 +2149,15 @@ void fuse_abort_conn(struct fuse_conn *fc) - fc->max_background = UINT_MAX; - flush_bg_queue(fc); - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - fiq->connected = 0; - list_splice_init(&fiq->pending, &to_end2); - list_for_each_entry(req, &to_end2, list) - clear_bit(FR_PENDING, &req->flags); - while (forget_pending(fiq)) - kfree(dequeue_forget(fiq, 1, NULL)); -- wake_up_all_locked(&fiq->waitq); -- spin_unlock(&fiq->waitq.lock); -+ wake_up_all(&fiq->waitq); -+ spin_unlock(&fiq->lock); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - end_polls(fc); - wake_up_all(&fc->blocked_waitq); -diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h -index e682f2eff6c0d..12a8a19b76da2 100644 ---- a/fs/fuse/fuse_i.h -+++ b/fs/fuse/fuse_i.h -@@ -387,6 +387,9 @@ struct fuse_iqueue { - /** Connection established */ - unsigned connected; - -+ /** Lock protecting accesses to members of this structure */ -+ spinlock_t lock; -+ - /** Readers of the connection are waiting on this */ - wait_queue_head_t waitq; - -diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c -index ffb61787d77af..d97619c52376f 100644 ---- a/fs/fuse/inode.c -+++ b/fs/fuse/inode.c -@@ -584,6 +584,7 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root) - static void fuse_iqueue_init(struct fuse_iqueue *fiq) - { - memset(fiq, 0, sizeof(struct fuse_iqueue)); -+ spin_lock_init(&fiq->lock); - init_waitqueue_head(&fiq->waitq); - INIT_LIST_HEAD(&fiq->pending); - INIT_LIST_HEAD(&fiq->interrupts); --- -2.20.1 - diff --git a/queue-4.14/series b/queue-4.14/series index b9da32e3a4d..0019de632a1 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -181,7 +181,6 @@ i2c-riic-clear-nack-in-tend-isr.patch cifs-fix-max-ea-value-size.patch cifs-fix-oplock-handling-for-smb-2.1-protocols.patch md-raid0-avoid-raid0-data-corruption-due-to-layout-c.patch -fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch mm-compaction.c-clear-total_-migrate-free-_scanned-b.patch btrfs-qgroup-drop-quota_root-and-fs_info-parameters-.patch btrfs-fix-race-setting-up-and-completing-qgroup-resc.patch diff --git a/queue-4.4/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch b/queue-4.4/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch deleted file mode 100644 index 9283abe68c7..00000000000 --- a/queue-4.4/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch +++ /dev/null @@ -1,401 +0,0 @@ -From a7cdb9053b16ef05bdd896df8e548215ff97223a Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Sun, 8 Sep 2019 20:15:18 -0700 -Subject: fuse: fix deadlock with aio poll and fuse_iqueue::waitq.lock - -From: Eric Biggers - -[ Upstream commit 76e43c8ccaa35c30d5df853013561145a0f750a5 ] - -When IOCB_CMD_POLL is used on the FUSE device, aio_poll() disables IRQs -and takes kioctx::ctx_lock, then fuse_iqueue::waitq.lock. - -This may have to wait for fuse_iqueue::waitq.lock to be released by one -of many places that take it with IRQs enabled. Since the IRQ handler -may take kioctx::ctx_lock, lockdep reports that a deadlock is possible. - -Fix it by protecting the state of struct fuse_iqueue with a separate -spinlock, and only accessing fuse_iqueue::waitq using the versions of -the waitqueue functions which do IRQ-safe locking internally. - -Reproducer: - - #include - #include - #include - #include - #include - #include - #include - - int main() - { - char opts[128]; - int fd = open("/dev/fuse", O_RDWR); - aio_context_t ctx = 0; - struct iocb cb = { .aio_lio_opcode = IOCB_CMD_POLL, .aio_fildes = fd }; - struct iocb *cbp = &cb; - - sprintf(opts, "fd=%d,rootmode=040000,user_id=0,group_id=0", fd); - mkdir("mnt", 0700); - mount("foo", "mnt", "fuse", 0, opts); - syscall(__NR_io_setup, 1, &ctx); - syscall(__NR_io_submit, ctx, 1, &cbp); - } - -Beginning of lockdep output: - - ===================================================== - WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected - 5.3.0-rc5 #9 Not tainted - ----------------------------------------------------- - syz_fuse/135 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: - 000000003590ceda (&fiq->waitq){+.+.}, at: spin_lock include/linux/spinlock.h:338 [inline] - 000000003590ceda (&fiq->waitq){+.+.}, at: aio_poll fs/aio.c:1751 [inline] - 000000003590ceda (&fiq->waitq){+.+.}, at: __io_submit_one.constprop.0+0x203/0x5b0 fs/aio.c:1825 - - and this task is already holding: - 0000000075037284 (&(&ctx->ctx_lock)->rlock){..-.}, at: spin_lock_irq include/linux/spinlock.h:363 [inline] - 0000000075037284 (&(&ctx->ctx_lock)->rlock){..-.}, at: aio_poll fs/aio.c:1749 [inline] - 0000000075037284 (&(&ctx->ctx_lock)->rlock){..-.}, at: __io_submit_one.constprop.0+0x1f4/0x5b0 fs/aio.c:1825 - which would create a new lock dependency: - (&(&ctx->ctx_lock)->rlock){..-.} -> (&fiq->waitq){+.+.} - - but this new dependency connects a SOFTIRQ-irq-safe lock: - (&(&ctx->ctx_lock)->rlock){..-.} - - [...] - -Reported-by: syzbot+af05535bb79520f95431@syzkaller.appspotmail.com -Reported-by: syzbot+d86c4426a01f60feddc7@syzkaller.appspotmail.com -Fixes: bfe4037e722e ("aio: implement IOCB_CMD_POLL") -Cc: # v4.19+ -Cc: Christoph Hellwig -Signed-off-by: Eric Biggers -Signed-off-by: Miklos Szeredi -Signed-off-by: Sasha Levin ---- - fs/fuse/dev.c | 89 +++++++++++++++++++++++++----------------------- - fs/fuse/fuse_i.h | 3 ++ - fs/fuse/inode.c | 1 + - 3 files changed, 50 insertions(+), 43 deletions(-) - -diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c -index f5d2d2340b44d..8cd5a775d13be 100644 ---- a/fs/fuse/dev.c -+++ b/fs/fuse/dev.c -@@ -338,7 +338,7 @@ static void queue_request(struct fuse_iqueue *fiq, struct fuse_req *req) - req->in.h.len = sizeof(struct fuse_in_header) + - len_args(req->in.numargs, (struct fuse_arg *) req->in.args); - list_add_tail(&req->list, &fiq->pending); -- wake_up_locked(&fiq->waitq); -+ wake_up(&fiq->waitq); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - } - -@@ -350,16 +350,16 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, - forget->forget_one.nodeid = nodeid; - forget->forget_one.nlookup = nlookup; - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (fiq->connected) { - fiq->forget_list_tail->next = forget; - fiq->forget_list_tail = forget; -- wake_up_locked(&fiq->waitq); -+ wake_up(&fiq->waitq); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - } else { - kfree(forget); - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - } - - static void flush_bg_queue(struct fuse_conn *fc) -@@ -372,10 +372,10 @@ static void flush_bg_queue(struct fuse_conn *fc) - req = list_entry(fc->bg_queue.next, struct fuse_req, list); - list_del(&req->list); - fc->active_background++; -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - req->in.h.unique = fuse_get_unique(fiq); - queue_request(fiq, req); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - } - } - -@@ -394,9 +394,9 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) - if (test_and_set_bit(FR_FINISHED, &req->flags)) - goto put_request; - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - list_del_init(&req->intr_entry); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - WARN_ON(test_bit(FR_PENDING, &req->flags)); - WARN_ON(test_bit(FR_SENT, &req->flags)); - if (test_bit(FR_BACKGROUND, &req->flags)) { -@@ -435,16 +435,16 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) - - static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) - { -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (test_bit(FR_FINISHED, &req->flags)) { -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - return; - } - if (list_empty(&req->intr_entry)) { - list_add_tail(&req->intr_entry, &fiq->interrupts); - wake_up_locked(&fiq->waitq); - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - } - -@@ -479,16 +479,16 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) - if (!err) - return; - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - /* Request is not yet in userspace, bail out */ - if (test_bit(FR_PENDING, &req->flags)) { - list_del(&req->list); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - __fuse_put_request(req); - req->out.h.error = -EINTR; - return; - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - } - - /* -@@ -503,9 +503,9 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) - struct fuse_iqueue *fiq = &fc->iq; - - BUG_ON(test_bit(FR_BACKGROUND, &req->flags)); -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (!fiq->connected) { -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - req->out.h.error = -ENOTCONN; - } else { - req->in.h.unique = fuse_get_unique(fiq); -@@ -513,7 +513,7 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) - /* acquire extra reference, since request is still needed - after request_end() */ - __fuse_get_request(req); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - request_wait_answer(fc, req); - /* Pairs with smp_wmb() in request_end() */ -@@ -647,12 +647,12 @@ static int fuse_request_send_notify_reply(struct fuse_conn *fc, - - __clear_bit(FR_ISREPLY, &req->flags); - req->in.h.unique = unique; -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (fiq->connected) { - queue_request(fiq, req); - err = 0; - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - return err; - } -@@ -1097,12 +1097,12 @@ static int request_pending(struct fuse_iqueue *fiq) - * Unlike other requests this is assembled on demand, without a need - * to allocate a separate fuse_req structure. - * -- * Called with fiq->waitq.lock held, releases it -+ * Called with fiq->lock held, releases it - */ - static int fuse_read_interrupt(struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, - size_t nbytes, struct fuse_req *req) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - struct fuse_in_header ih; - struct fuse_interrupt_in arg; -@@ -1118,7 +1118,7 @@ __releases(fiq->waitq.lock) - ih.unique = req->intr_unique; - arg.unique = req->in.h.unique; - -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - if (nbytes < reqsize) - return -EINVAL; - -@@ -1155,7 +1155,7 @@ static struct fuse_forget_link *dequeue_forget(struct fuse_iqueue *fiq, - static int fuse_read_single_forget(struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, - size_t nbytes) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - int err; - struct fuse_forget_link *forget = dequeue_forget(fiq, 1, NULL); -@@ -1169,7 +1169,7 @@ __releases(fiq->waitq.lock) - .len = sizeof(ih) + sizeof(arg), - }; - -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - kfree(forget); - if (nbytes < ih.len) - return -EINVAL; -@@ -1187,7 +1187,7 @@ __releases(fiq->waitq.lock) - - static int fuse_read_batch_forget(struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, size_t nbytes) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - int err; - unsigned max_forgets; -@@ -1201,13 +1201,13 @@ __releases(fiq->waitq.lock) - }; - - if (nbytes < ih.len) { -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - return -EINVAL; - } - - max_forgets = (nbytes - ih.len) / sizeof(struct fuse_forget_one); - head = dequeue_forget(fiq, max_forgets, &count); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - arg.count = count; - ih.len += count * sizeof(struct fuse_forget_one); -@@ -1237,7 +1237,7 @@ __releases(fiq->waitq.lock) - static int fuse_read_forget(struct fuse_conn *fc, struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, - size_t nbytes) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - if (fc->minor < 16 || fiq->forget_list_head.next->next == NULL) - return fuse_read_single_forget(fiq, cs, nbytes); -@@ -1266,16 +1266,19 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, - unsigned reqsize; - - restart: -- spin_lock(&fiq->waitq.lock); -- err = -EAGAIN; -- if ((file->f_flags & O_NONBLOCK) && fiq->connected && -- !request_pending(fiq)) -- goto err_unlock; -+ for (;;) { -+ spin_lock(&fiq->lock); -+ if (!fiq->connected || request_pending(fiq)) -+ break; -+ spin_unlock(&fiq->lock); - -- err = wait_event_interruptible_exclusive_locked(fiq->waitq, -+ if (file->f_flags & O_NONBLOCK) -+ return -EAGAIN; -+ err = wait_event_interruptible_exclusive(fiq->waitq, - !fiq->connected || request_pending(fiq)); -- if (err) -- goto err_unlock; -+ if (err) -+ return err; -+ } - - err = -ENODEV; - if (!fiq->connected) -@@ -1298,7 +1301,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, - req = list_entry(fiq->pending.next, struct fuse_req, list); - clear_bit(FR_PENDING, &req->flags); - list_del_init(&req->list); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - in = &req->in; - reqsize = in->h.len; -@@ -1354,7 +1357,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, - return err; - - err_unlock: -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - return err; - } - -@@ -2098,12 +2101,12 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait) - fiq = &fud->fc->iq; - poll_wait(file, &fiq->waitq, wait); - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (!fiq->connected) - mask = POLLERR; - else if (request_pending(fiq)) - mask |= POLLIN | POLLRDNORM; -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - return mask; - } -@@ -2194,15 +2197,15 @@ void fuse_abort_conn(struct fuse_conn *fc) - fc->max_background = UINT_MAX; - flush_bg_queue(fc); - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - fiq->connected = 0; - list_splice_init(&fiq->pending, &to_end2); - list_for_each_entry(req, &to_end2, list) - clear_bit(FR_PENDING, &req->flags); - while (forget_pending(fiq)) - kfree(dequeue_forget(fiq, 1, NULL)); -- wake_up_all_locked(&fiq->waitq); -- spin_unlock(&fiq->waitq.lock); -+ wake_up_all(&fiq->waitq); -+ spin_unlock(&fiq->lock); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - end_polls(fc); - wake_up_all(&fc->blocked_waitq); -diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h -index c6eb35a95fcc9..5109f1acda0df 100644 ---- a/fs/fuse/fuse_i.h -+++ b/fs/fuse/fuse_i.h -@@ -390,6 +390,9 @@ struct fuse_iqueue { - /** Connection established */ - unsigned connected; - -+ /** Lock protecting accesses to members of this structure */ -+ spinlock_t lock; -+ - /** Readers of the connection are waiting on this */ - wait_queue_head_t waitq; - -diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c -index 4b2eb65be0d40..b353787fa35a0 100644 ---- a/fs/fuse/inode.c -+++ b/fs/fuse/inode.c -@@ -567,6 +567,7 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root) - static void fuse_iqueue_init(struct fuse_iqueue *fiq) - { - memset(fiq, 0, sizeof(struct fuse_iqueue)); -+ spin_lock_init(&fiq->lock); - init_waitqueue_head(&fiq->waitq); - INIT_LIST_HEAD(&fiq->pending); - INIT_LIST_HEAD(&fiq->interrupts); --- -2.20.1 - diff --git a/queue-4.4/series b/queue-4.4/series index 9c4fff8e456..3abf4765429 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -96,5 +96,4 @@ cifs-fix-oplock-handling-for-smb-2.1-protocols.patch ovl-filter-of-trusted-xattr-results-in-audit.patch btrfs-fix-use-after-free-when-using-the-tree-modification-log.patch btrfs-relinquish-cpus-in-btrfs_compare_trees.patch -fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch btrfs-fix-race-setting-up-and-completing-qgroup-resc.patch diff --git a/queue-4.9/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch b/queue-4.9/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch deleted file mode 100644 index e8ed0cabb9a..00000000000 --- a/queue-4.9/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch +++ /dev/null @@ -1,401 +0,0 @@ -From 5242268a759931c34ad6262d1646f3eb45c8d19f Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Sun, 8 Sep 2019 20:15:18 -0700 -Subject: fuse: fix deadlock with aio poll and fuse_iqueue::waitq.lock - -From: Eric Biggers - -[ Upstream commit 76e43c8ccaa35c30d5df853013561145a0f750a5 ] - -When IOCB_CMD_POLL is used on the FUSE device, aio_poll() disables IRQs -and takes kioctx::ctx_lock, then fuse_iqueue::waitq.lock. - -This may have to wait for fuse_iqueue::waitq.lock to be released by one -of many places that take it with IRQs enabled. Since the IRQ handler -may take kioctx::ctx_lock, lockdep reports that a deadlock is possible. - -Fix it by protecting the state of struct fuse_iqueue with a separate -spinlock, and only accessing fuse_iqueue::waitq using the versions of -the waitqueue functions which do IRQ-safe locking internally. - -Reproducer: - - #include - #include - #include - #include - #include - #include - #include - - int main() - { - char opts[128]; - int fd = open("/dev/fuse", O_RDWR); - aio_context_t ctx = 0; - struct iocb cb = { .aio_lio_opcode = IOCB_CMD_POLL, .aio_fildes = fd }; - struct iocb *cbp = &cb; - - sprintf(opts, "fd=%d,rootmode=040000,user_id=0,group_id=0", fd); - mkdir("mnt", 0700); - mount("foo", "mnt", "fuse", 0, opts); - syscall(__NR_io_setup, 1, &ctx); - syscall(__NR_io_submit, ctx, 1, &cbp); - } - -Beginning of lockdep output: - - ===================================================== - WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected - 5.3.0-rc5 #9 Not tainted - ----------------------------------------------------- - syz_fuse/135 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: - 000000003590ceda (&fiq->waitq){+.+.}, at: spin_lock include/linux/spinlock.h:338 [inline] - 000000003590ceda (&fiq->waitq){+.+.}, at: aio_poll fs/aio.c:1751 [inline] - 000000003590ceda (&fiq->waitq){+.+.}, at: __io_submit_one.constprop.0+0x203/0x5b0 fs/aio.c:1825 - - and this task is already holding: - 0000000075037284 (&(&ctx->ctx_lock)->rlock){..-.}, at: spin_lock_irq include/linux/spinlock.h:363 [inline] - 0000000075037284 (&(&ctx->ctx_lock)->rlock){..-.}, at: aio_poll fs/aio.c:1749 [inline] - 0000000075037284 (&(&ctx->ctx_lock)->rlock){..-.}, at: __io_submit_one.constprop.0+0x1f4/0x5b0 fs/aio.c:1825 - which would create a new lock dependency: - (&(&ctx->ctx_lock)->rlock){..-.} -> (&fiq->waitq){+.+.} - - but this new dependency connects a SOFTIRQ-irq-safe lock: - (&(&ctx->ctx_lock)->rlock){..-.} - - [...] - -Reported-by: syzbot+af05535bb79520f95431@syzkaller.appspotmail.com -Reported-by: syzbot+d86c4426a01f60feddc7@syzkaller.appspotmail.com -Fixes: bfe4037e722e ("aio: implement IOCB_CMD_POLL") -Cc: # v4.19+ -Cc: Christoph Hellwig -Signed-off-by: Eric Biggers -Signed-off-by: Miklos Szeredi -Signed-off-by: Sasha Levin ---- - fs/fuse/dev.c | 89 +++++++++++++++++++++++++----------------------- - fs/fuse/fuse_i.h | 3 ++ - fs/fuse/inode.c | 1 + - 3 files changed, 50 insertions(+), 43 deletions(-) - -diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c -index 8016cd059db12..638ec50e606e2 100644 ---- a/fs/fuse/dev.c -+++ b/fs/fuse/dev.c -@@ -319,7 +319,7 @@ static void queue_request(struct fuse_iqueue *fiq, struct fuse_req *req) - req->in.h.len = sizeof(struct fuse_in_header) + - len_args(req->in.numargs, (struct fuse_arg *) req->in.args); - list_add_tail(&req->list, &fiq->pending); -- wake_up_locked(&fiq->waitq); -+ wake_up(&fiq->waitq); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - } - -@@ -331,16 +331,16 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, - forget->forget_one.nodeid = nodeid; - forget->forget_one.nlookup = nlookup; - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (fiq->connected) { - fiq->forget_list_tail->next = forget; - fiq->forget_list_tail = forget; -- wake_up_locked(&fiq->waitq); -+ wake_up(&fiq->waitq); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - } else { - kfree(forget); - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - } - - static void flush_bg_queue(struct fuse_conn *fc) -@@ -353,10 +353,10 @@ static void flush_bg_queue(struct fuse_conn *fc) - req = list_entry(fc->bg_queue.next, struct fuse_req, list); - list_del(&req->list); - fc->active_background++; -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - req->in.h.unique = fuse_get_unique(fiq); - queue_request(fiq, req); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - } - } - -@@ -375,9 +375,9 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) - if (test_and_set_bit(FR_FINISHED, &req->flags)) - goto put_request; - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - list_del_init(&req->intr_entry); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - WARN_ON(test_bit(FR_PENDING, &req->flags)); - WARN_ON(test_bit(FR_SENT, &req->flags)); - if (test_bit(FR_BACKGROUND, &req->flags)) { -@@ -416,16 +416,16 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) - - static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) - { -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (test_bit(FR_FINISHED, &req->flags)) { -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - return; - } - if (list_empty(&req->intr_entry)) { - list_add_tail(&req->intr_entry, &fiq->interrupts); - wake_up_locked(&fiq->waitq); - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - } - -@@ -455,16 +455,16 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) - if (!err) - return; - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - /* Request is not yet in userspace, bail out */ - if (test_bit(FR_PENDING, &req->flags)) { - list_del(&req->list); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - __fuse_put_request(req); - req->out.h.error = -EINTR; - return; - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - } - - /* -@@ -479,9 +479,9 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) - struct fuse_iqueue *fiq = &fc->iq; - - BUG_ON(test_bit(FR_BACKGROUND, &req->flags)); -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (!fiq->connected) { -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - req->out.h.error = -ENOTCONN; - } else { - req->in.h.unique = fuse_get_unique(fiq); -@@ -489,7 +489,7 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) - /* acquire extra reference, since request is still needed - after request_end() */ - __fuse_get_request(req); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - request_wait_answer(fc, req); - /* Pairs with smp_wmb() in request_end() */ -@@ -623,12 +623,12 @@ static int fuse_request_send_notify_reply(struct fuse_conn *fc, - - __clear_bit(FR_ISREPLY, &req->flags); - req->in.h.unique = unique; -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (fiq->connected) { - queue_request(fiq, req); - err = 0; - } -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - return err; - } -@@ -1072,12 +1072,12 @@ static int request_pending(struct fuse_iqueue *fiq) - * Unlike other requests this is assembled on demand, without a need - * to allocate a separate fuse_req structure. - * -- * Called with fiq->waitq.lock held, releases it -+ * Called with fiq->lock held, releases it - */ - static int fuse_read_interrupt(struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, - size_t nbytes, struct fuse_req *req) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - struct fuse_in_header ih; - struct fuse_interrupt_in arg; -@@ -1093,7 +1093,7 @@ __releases(fiq->waitq.lock) - ih.unique = req->intr_unique; - arg.unique = req->in.h.unique; - -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - if (nbytes < reqsize) - return -EINVAL; - -@@ -1130,7 +1130,7 @@ static struct fuse_forget_link *dequeue_forget(struct fuse_iqueue *fiq, - static int fuse_read_single_forget(struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, - size_t nbytes) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - int err; - struct fuse_forget_link *forget = dequeue_forget(fiq, 1, NULL); -@@ -1144,7 +1144,7 @@ __releases(fiq->waitq.lock) - .len = sizeof(ih) + sizeof(arg), - }; - -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - kfree(forget); - if (nbytes < ih.len) - return -EINVAL; -@@ -1162,7 +1162,7 @@ __releases(fiq->waitq.lock) - - static int fuse_read_batch_forget(struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, size_t nbytes) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - int err; - unsigned max_forgets; -@@ -1176,13 +1176,13 @@ __releases(fiq->waitq.lock) - }; - - if (nbytes < ih.len) { -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - return -EINVAL; - } - - max_forgets = (nbytes - ih.len) / sizeof(struct fuse_forget_one); - head = dequeue_forget(fiq, max_forgets, &count); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - arg.count = count; - ih.len += count * sizeof(struct fuse_forget_one); -@@ -1212,7 +1212,7 @@ __releases(fiq->waitq.lock) - static int fuse_read_forget(struct fuse_conn *fc, struct fuse_iqueue *fiq, - struct fuse_copy_state *cs, - size_t nbytes) --__releases(fiq->waitq.lock) -+__releases(fiq->lock) - { - if (fc->minor < 16 || fiq->forget_list_head.next->next == NULL) - return fuse_read_single_forget(fiq, cs, nbytes); -@@ -1241,16 +1241,19 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, - unsigned reqsize; - - restart: -- spin_lock(&fiq->waitq.lock); -- err = -EAGAIN; -- if ((file->f_flags & O_NONBLOCK) && fiq->connected && -- !request_pending(fiq)) -- goto err_unlock; -+ for (;;) { -+ spin_lock(&fiq->lock); -+ if (!fiq->connected || request_pending(fiq)) -+ break; -+ spin_unlock(&fiq->lock); - -- err = wait_event_interruptible_exclusive_locked(fiq->waitq, -+ if (file->f_flags & O_NONBLOCK) -+ return -EAGAIN; -+ err = wait_event_interruptible_exclusive(fiq->waitq, - !fiq->connected || request_pending(fiq)); -- if (err) -- goto err_unlock; -+ if (err) -+ return err; -+ } - - err = -ENODEV; - if (!fiq->connected) -@@ -1273,7 +1276,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, - req = list_entry(fiq->pending.next, struct fuse_req, list); - clear_bit(FR_PENDING, &req->flags); - list_del_init(&req->list); -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - in = &req->in; - reqsize = in->h.len; -@@ -1329,7 +1332,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, - return err; - - err_unlock: -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - return err; - } - -@@ -2040,12 +2043,12 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait) - fiq = &fud->fc->iq; - poll_wait(file, &fiq->waitq, wait); - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - if (!fiq->connected) - mask = POLLERR; - else if (request_pending(fiq)) - mask |= POLLIN | POLLRDNORM; -- spin_unlock(&fiq->waitq.lock); -+ spin_unlock(&fiq->lock); - - return mask; - } -@@ -2136,15 +2139,15 @@ void fuse_abort_conn(struct fuse_conn *fc) - fc->max_background = UINT_MAX; - flush_bg_queue(fc); - -- spin_lock(&fiq->waitq.lock); -+ spin_lock(&fiq->lock); - fiq->connected = 0; - list_splice_init(&fiq->pending, &to_end2); - list_for_each_entry(req, &to_end2, list) - clear_bit(FR_PENDING, &req->flags); - while (forget_pending(fiq)) - kfree(dequeue_forget(fiq, 1, NULL)); -- wake_up_all_locked(&fiq->waitq); -- spin_unlock(&fiq->waitq.lock); -+ wake_up_all(&fiq->waitq); -+ spin_unlock(&fiq->lock); - kill_fasync(&fiq->fasync, SIGIO, POLL_IN); - end_polls(fc); - wake_up_all(&fc->blocked_waitq); -diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h -index 1c905c7666dec..ac9add774db77 100644 ---- a/fs/fuse/fuse_i.h -+++ b/fs/fuse/fuse_i.h -@@ -385,6 +385,9 @@ struct fuse_iqueue { - /** Connection established */ - unsigned connected; - -+ /** Lock protecting accesses to members of this structure */ -+ spinlock_t lock; -+ - /** Readers of the connection are waiting on this */ - wait_queue_head_t waitq; - -diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c -index 7a9b1069d267b..2c942a8279040 100644 ---- a/fs/fuse/inode.c -+++ b/fs/fuse/inode.c -@@ -590,6 +590,7 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root) - static void fuse_iqueue_init(struct fuse_iqueue *fiq) - { - memset(fiq, 0, sizeof(struct fuse_iqueue)); -+ spin_lock_init(&fiq->lock); - init_waitqueue_head(&fiq->waitq); - INIT_LIST_HEAD(&fiq->pending); - INIT_LIST_HEAD(&fiq->interrupts); --- -2.20.1 - diff --git a/queue-4.9/series b/queue-4.9/series index c00d8ddfcd5..b0042255d6b 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -125,6 +125,5 @@ hwrng-core-don-t-wait-on-add_early_randomness.patch i2c-riic-clear-nack-in-tend-isr.patch cifs-fix-max-ea-value-size.patch cifs-fix-oplock-handling-for-smb-2.1-protocols.patch -fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch btrfs-qgroup-drop-quota_root-and-fs_info-parameters-.patch btrfs-fix-race-setting-up-and-completing-qgroup-resc.patch