]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
drop fuse patch that didn't need to be backported as far.
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Oct 2019 15:18:23 +0000 (17:18 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Oct 2019 15:18:23 +0000 (17:18 +0200)
queue-4.14/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch [deleted file]
queue-4.14/series
queue-4.4/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch [deleted file]
queue-4.4/series
queue-4.9/fuse-fix-deadlock-with-aio-poll-and-fuse_iqueue-wait.patch [deleted file]
queue-4.9/series

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 (file)
index c81eb80..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-From 893cbb6cdc091ab6da8f0590ca625cc58e5650d2 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 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
-
index b9da32e3a4dbfd3c7f4f0cac18c32ae330380019..0019de632a1572ab31ff53c2649ac3fa5587de16 100644 (file)
@@ -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 (file)
index 9283abe..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-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
-
index 9c4fff8e456ae45a9fe2cbbfd9cff663edc3cf89..3abf4765429aa2a3df9cb517792fc9154490b32d 100644 (file)
@@ -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 (file)
index e8ed0ca..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-From 5242268a759931c34ad6262d1646f3eb45c8d19f 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 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
-
index c00d8ddfcd5bca2232a53f6a03e1b824f8e6706e..b0042255d6b4ad007751516743bd5aaad5010a63 100644 (file)
@@ -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