summaryrefslogtreecommitdiffstats
path: root/fs/aio.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-04 22:24:27 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-04 22:24:27 +0100
commit4f9020ffde71ddb92bc2f65ce0b00232bc88c590 (patch)
treee67b1f3499f255477cadf5f418319fffed117874 /fs/aio.c
parentget rid of legacy 'get_ds()' function (diff)
parentaio: Fix locking in aio_poll() (diff)
downloadlinux-4f9020ffde71ddb92bc2f65ce0b00232bc88c590.tar.xz
linux-4f9020ffde71ddb92bc2f65ce0b00232bc88c590.zip
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro: "Assorted fixes that sat in -next for a while, all over the place" * 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: aio: Fix locking in aio_poll() exec: Fix mem leak in kernel_read_file copy_mount_string: Limit string length to PATH_MAX cgroup: saner refcounting for cgroup_root fix cgroup_do_mount() handling of failure exits
Diffstat (limited to 'fs/aio.c')
-rw-r--r--fs/aio.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 82c08422b0f4..3d9669d011b9 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1666,6 +1666,7 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
struct poll_iocb *req = container_of(wait, struct poll_iocb, wait);
struct aio_kiocb *iocb = container_of(req, struct aio_kiocb, poll);
__poll_t mask = key_to_poll(key);
+ unsigned long flags;
req->woken = true;
@@ -1674,10 +1675,15 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
if (!(mask & req->events))
return 0;
- /* try to complete the iocb inline if we can: */
- if (spin_trylock(&iocb->ki_ctx->ctx_lock)) {
+ /*
+ * Try to complete the iocb inline if we can. Use
+ * irqsave/irqrestore because not all filesystems (e.g. fuse)
+ * call this function with IRQs disabled and because IRQs
+ * have to be disabled before ctx_lock is obtained.
+ */
+ if (spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) {
list_del(&iocb->ki_list);
- spin_unlock(&iocb->ki_ctx->ctx_lock);
+ spin_unlock_irqrestore(&iocb->ki_ctx->ctx_lock, flags);
list_del_init(&req->wait.entry);
aio_poll_complete(iocb, mask);