--- /dev/null
+From 90981de1b9a37ac9847125499bd66ea70a642bbd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Sep 2019 10:49:54 +0100
+Subject: Btrfs: fix race setting up and completing qgroup rescan workers
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit 13fc1d271a2e3ab8a02071e711add01fab9271f6 ]
+
+There is a race between setting up a qgroup rescan worker and completing
+a qgroup rescan worker that can lead to callers of the qgroup rescan wait
+ioctl to either not wait for the rescan worker to complete or to hang
+forever due to missing wake ups. The following diagram shows a sequence
+of steps that illustrates the race.
+
+ CPU 1 CPU 2 CPU 3
+
+ btrfs_ioctl_quota_rescan()
+ btrfs_qgroup_rescan()
+ qgroup_rescan_init()
+ mutex_lock(&fs_info->qgroup_rescan_lock)
+ spin_lock(&fs_info->qgroup_lock)
+
+ fs_info->qgroup_flags |=
+ BTRFS_QGROUP_STATUS_FLAG_RESCAN
+
+ init_completion(
+ &fs_info->qgroup_rescan_completion)
+
+ fs_info->qgroup_rescan_running = true
+
+ mutex_unlock(&fs_info->qgroup_rescan_lock)
+ spin_unlock(&fs_info->qgroup_lock)
+
+ btrfs_init_work()
+ --> starts the worker
+
+ btrfs_qgroup_rescan_worker()
+ mutex_lock(&fs_info->qgroup_rescan_lock)
+
+ fs_info->qgroup_flags &=
+ ~BTRFS_QGROUP_STATUS_FLAG_RESCAN
+
+ mutex_unlock(&fs_info->qgroup_rescan_lock)
+
+ starts transaction, updates qgroup status
+ item, etc
+
+ btrfs_ioctl_quota_rescan()
+ btrfs_qgroup_rescan()
+ qgroup_rescan_init()
+ mutex_lock(&fs_info->qgroup_rescan_lock)
+ spin_lock(&fs_info->qgroup_lock)
+
+ fs_info->qgroup_flags |=
+ BTRFS_QGROUP_STATUS_FLAG_RESCAN
+
+ init_completion(
+ &fs_info->qgroup_rescan_completion)
+
+ fs_info->qgroup_rescan_running = true
+
+ mutex_unlock(&fs_info->qgroup_rescan_lock)
+ spin_unlock(&fs_info->qgroup_lock)
+
+ btrfs_init_work()
+ --> starts another worker
+
+ mutex_lock(&fs_info->qgroup_rescan_lock)
+
+ fs_info->qgroup_rescan_running = false
+
+ mutex_unlock(&fs_info->qgroup_rescan_lock)
+
+ complete_all(&fs_info->qgroup_rescan_completion)
+
+Before the rescan worker started by the task at CPU 3 completes, if
+another task calls btrfs_ioctl_quota_rescan(), it will get -EINPROGRESS
+because the flag BTRFS_QGROUP_STATUS_FLAG_RESCAN is set at
+fs_info->qgroup_flags, which is expected and correct behaviour.
+
+However if other task calls btrfs_ioctl_quota_rescan_wait() before the
+rescan worker started by the task at CPU 3 completes, it will return
+immediately without waiting for the new rescan worker to complete,
+because fs_info->qgroup_rescan_running is set to false by CPU 2.
+
+This race is making test case btrfs/171 (from fstests) to fail often:
+
+ btrfs/171 9s ... - output mismatch (see /home/fdmanana/git/hub/xfstests/results//btrfs/171.out.bad)
+ --- tests/btrfs/171.out 2018-09-16 21:30:48.505104287 +0100
+ +++ /home/fdmanana/git/hub/xfstests/results//btrfs/171.out.bad 2019-09-19 02:01:36.938486039 +0100
+ @@ -1,2 +1,3 @@
+ QA output created by 171
+ +ERROR: quota rescan failed: Operation now in progress
+ Silence is golden
+ ...
+ (Run 'diff -u /home/fdmanana/git/hub/xfstests/tests/btrfs/171.out /home/fdmanana/git/hub/xfstests/results//btrfs/171.out.bad' to see the entire diff)
+
+That is because the test calls the btrfs-progs commands "qgroup quota
+rescan -w", "qgroup assign" and "qgroup remove" in a sequence that makes
+calls to the rescan start ioctl fail with -EINPROGRESS (note the "btrfs"
+commands 'qgroup assign' and 'qgroup remove' often call the rescan start
+ioctl after calling the qgroup assign ioctl,
+btrfs_ioctl_qgroup_assign()), since previous waits didn't actually wait
+for a rescan worker to complete.
+
+Another problem the race can cause is missing wake ups for waiters,
+since the call to complete_all() happens outside a critical section and
+after clearing the flag BTRFS_QGROUP_STATUS_FLAG_RESCAN. In the sequence
+diagram above, if we have a waiter for the first rescan task (executed
+by CPU 2), then fs_info->qgroup_rescan_completion.wait is not empty, and
+if after the rescan worker clears BTRFS_QGROUP_STATUS_FLAG_RESCAN and
+before it calls complete_all() against
+fs_info->qgroup_rescan_completion, the task at CPU 3 calls
+init_completion() against fs_info->qgroup_rescan_completion which
+re-initilizes its wait queue to an empty queue, therefore causing the
+rescan worker at CPU 2 to call complete_all() against an empty queue,
+never waking up the task waiting for that rescan worker.
+
+Fix this by clearing BTRFS_QGROUP_STATUS_FLAG_RESCAN and setting
+fs_info->qgroup_rescan_running to false in the same critical section,
+delimited by the mutex fs_info->qgroup_rescan_lock, as well as doing the
+call to complete_all() in that same critical section. This gives the
+protection needed to avoid rescan wait ioctl callers not waiting for a
+running rescan worker and the lost wake ups problem, since setting that
+rescan flag and boolean as well as initializing the wait queue is done
+already in a critical section delimited by that mutex (at
+qgroup_rescan_init()).
+
+Fixes: 57254b6ebce4ce ("Btrfs: add ioctl to wait for qgroup rescan completion")
+Fixes: d2c609b834d62f ("btrfs: properly track when rescan worker is running")
+CC: stable@vger.kernel.org # 4.4+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/qgroup.c | 33 +++++++++++++++++++--------------
+ 1 file changed, 19 insertions(+), 14 deletions(-)
+
+diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
+index 90e29d40aa82e..734babb6626c4 100644
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -2328,9 +2328,6 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
+ btrfs_free_path(path);
+
+ mutex_lock(&fs_info->qgroup_rescan_lock);
+- if (!btrfs_fs_closing(fs_info))
+- fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
+-
+ if (err > 0 &&
+ fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) {
+ fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+@@ -2346,16 +2343,30 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
+ trans = btrfs_start_transaction(fs_info->quota_root, 1);
+ if (IS_ERR(trans)) {
+ err = PTR_ERR(trans);
++ trans = NULL;
+ btrfs_err(fs_info,
+ "fail to start transaction for status update: %d\n",
+ err);
+- goto done;
+ }
+- ret = update_qgroup_status_item(trans, fs_info, fs_info->quota_root);
+- if (ret < 0) {
+- err = ret;
+- btrfs_err(fs_info, "fail to update qgroup status: %d\n", err);
++
++ mutex_lock(&fs_info->qgroup_rescan_lock);
++ if (!btrfs_fs_closing(fs_info))
++ fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
++ if (trans) {
++ ret = update_qgroup_status_item(trans, fs_info, fs_info->quota_root);
++ if (ret < 0) {
++ err = ret;
++ btrfs_err(fs_info, "fail to update qgroup status: %d",
++ err);
++ }
+ }
++ fs_info->qgroup_rescan_running = false;
++ complete_all(&fs_info->qgroup_rescan_completion);
++ mutex_unlock(&fs_info->qgroup_rescan_lock);
++
++ if (!trans)
++ return;
++
+ btrfs_end_transaction(trans, fs_info->quota_root);
+
+ if (btrfs_fs_closing(fs_info)) {
+@@ -2366,12 +2377,6 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
+ } else {
+ btrfs_err(fs_info, "qgroup scan failed with %d", err);
+ }
+-
+-done:
+- mutex_lock(&fs_info->qgroup_rescan_lock);
+- fs_info->qgroup_rescan_running = false;
+- mutex_unlock(&fs_info->qgroup_rescan_lock);
+- complete_all(&fs_info->qgroup_rescan_completion);
+ }
+
+ /*
+--
+2.20.1
+
--- /dev/null
+From a7cdb9053b16ef05bdd896df8e548215ff97223a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Sep 2019 20:15:18 -0700
+Subject: fuse: fix deadlock with aio poll and fuse_iqueue::waitq.lock
+
+From: Eric Biggers <ebiggers@google.com>
+
+[ 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 <fcntl.h>
+ #include <stdio.h>
+ #include <sys/mount.h>
+ #include <sys/stat.h>
+ #include <sys/syscall.h>
+ #include <unistd.h>
+ #include <linux/aio_abi.h>
+
+ 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: <stable@vger.kernel.org> # v4.19+
+Cc: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+