On Wed, Feb 06, 2019 at 09:36:26AM +0100, Miklos Szeredi wrote: > Yep. And is AIO doing anything in irq context? If so, why? Because all waitqueues can be woken, and often are woken from irq context. > > Would it make sense to just disable AIO on file descriptors where it makes zero > sense? using aio poll makes sense on every fd, just like you can use epoll or the upcoming io_uring poll on every fd. Just use the waitqueue API properly in fuse and we are done: diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index a5e516a40e7a..1c693bb6339a 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -387,7 +387,7 @@ 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_irq(&fiq->waitq.lock); if (fiq->connected) { fiq->forget_list_tail->next = forget; fiq->forget_list_tail = forget; @@ -396,7 +396,7 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, } else { kfree(forget); } - spin_unlock(&fiq->waitq.lock); + spin_unlock_irq(&fiq->waitq.lock); } static void flush_bg_queue(struct fuse_conn *fc) @@ -410,10 +410,10 @@ static void flush_bg_queue(struct fuse_conn *fc) req = list_first_entry(&fc->bg_queue, struct fuse_req, list); list_del(&req->list); fc->active_background++; - spin_lock(&fiq->waitq.lock); + spin_lock_irq(&fiq->waitq.lock); req->in.h.unique = fuse_get_unique(fiq); queue_request(fiq, req); - spin_unlock(&fiq->waitq.lock); + spin_unlock_irq(&fiq->waitq.lock); } } @@ -472,7 +472,7 @@ 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_irq(&fiq->waitq.lock); if (test_bit(FR_FINISHED, &req->flags)) { spin_unlock(&fiq->waitq.lock); return; @@ -481,7 +481,7 @@ static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) list_add_tail(&req->intr_entry, &fiq->interrupts); wake_up_locked(&fiq->waitq); } - spin_unlock(&fiq->waitq.lock); + spin_unlock_irq(&fiq->waitq.lock); kill_fasync(&fiq->fasync, SIGIO, POLL_IN); } @@ -535,9 +535,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_irq(&fiq->waitq.lock); if (!fiq->connected) { - spin_unlock(&fiq->waitq.lock); + spin_unlock_irq(&fiq->waitq.lock); req->out.h.error = -ENOTCONN; } else { req->in.h.unique = fuse_get_unique(fiq); @@ -545,7 +545,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_irq(&fiq->waitq.lock); request_wait_answer(fc, req); /* Pairs with smp_wmb() in request_end() */ @@ -676,12 +676,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_irq(&fiq->waitq.lock); if (fiq->connected) { queue_request(fiq, req); err = 0; } - spin_unlock(&fiq->waitq.lock); + spin_unlock_irq(&fiq->waitq.lock); return err; }